package com.ruoyi.exam.serive.impl;

import com.ruoyi.common.vo.PageResult;
import com.ruoyi.exam.domain.ExamInfo;
import com.ruoyi.exam.domain.ExamTheory;
import com.ruoyi.exam.enums.ExamStatusEnum;
import com.ruoyi.exam.mapper.ExamInfoMapper;
import com.ruoyi.exam.mapper.ExamTheoryMapper;
import com.ruoyi.exam.serive.IExamScoreService;
import com.ruoyi.exam.serive.IExamService;
import com.ruoyi.exam.vo.ExamAnswersVO;
import com.ruoyi.exam.vo.ExamInfoSearchVO;
import com.ruoyi.exam.vo.ExamScoreSubmitVO;
import com.ruoyi.questionBank.domain.AnswerResult;
import com.ruoyi.questionBank.domain.BuildPaperRule;
import com.ruoyi.questionBank.domain.ExamPaper;
import com.ruoyi.questionBank.service.IExamPaperService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Slf4j
@Service
public class ExamServiceImpl implements IExamService {
    @Autowired
    private ExamInfoMapper examInfoMapper;
    @Autowired
    private ExamTheoryMapper examTheoryMapper;
    @Autowired
    private IExamPaperService paperService;
    @Autowired
    private IExamScoreService scoreService;

    @Override
    public int submitAnswer(ExamAnswersVO answersVO) {
        int examId = answersVO.getExamId();
        ExamInfo examInfo = getExamInfo(examId);
        AnswerResult answerResult = paperService.submitAnswer(examInfo.getExamTheory().getPaperId(), answersVO.getAnswers());

        ExamScoreSubmitVO scoreSubmitVO = new ExamScoreSubmitVO();
        scoreSubmitVO.setUid(answersVO.getUid());
        scoreSubmitVO.setExamId(examId);
        scoreSubmitVO.setScores(answerResult.getScore());
        scoreSubmitVO.setTime(answersVO.getTime());
        scoreService.submitTheoryScore(scoreSubmitVO);

        return answerResult.getScore();
    }

    @Override
    public ExamInfo getLastExam() {
        ExamInfo info = examInfoMapper.getLastExam();
        if (info != null) {
            ExamTheory theory = examTheoryMapper.getByExamInfoId(info.getId());
            info.setExamTheory(theory);

            checkAndSetStatus(info);
        }

        return info;
    }

    @Override
    public ExamInfo getExamInfo(int examId) {
        ExamInfo info = examInfoMapper.getById(examId);
        ExamTheory theory = examTheoryMapper.getByExamInfoId(examId);
        info.setExamTheory(theory);

        checkAndSetStatus(info);

        return info;
    }


    @Override
    public PageResult<ExamInfo> getPage(ExamInfoSearchVO vo) {
        int total = examInfoMapper.size(vo);
        PageResult result = new PageResult(vo.getPageNo(), vo.getPageSize(), total);
        if (total > 0) {
            List<ExamInfo> list = examInfoMapper.getList(vo);
            for (ExamInfo info : list) {
                ExamTheory examTheory = examTheoryMapper.getByExamInfoId(info.getId());
                info.setExamTheory(examTheory);

                checkAndSetStatus(info);
            }
            result.addAll(list);
        }
        return result;
    }

    /**
     * 检查状态是否需要更新，需要时则更新状态
     */
    private void checkAndSetStatus(ExamInfo info) {
        int oldStatus = info.getStatus();
        if (info.checkAndSetStatus()) {
            examInfoMapper.updateExamInfo(info);
            onExamStatusChange(info.getId() ,oldStatus ,info.getStatus());
        }
    }

    @Override
    @Transactional
    public void addExam(ExamInfo examInfo) {
        if (examInfo.getStatus() == null) {
            examInfo.setDefaultStatus();
        }
        examInfo.verifyComplete();

        if (examInfo.getStatus() != ExamStatusEnum.UN_ENABLED.getStatus()
                && examInfo.getStatus() != ExamStatusEnum.UN_ENABLED.getStatus()) {
            checkExamInProgressOnly();
        }

        examInfo.setDataTime();

//        BuildPaperRule rule = new BuildPaperRule();
//        rule.setRadioSize(2);
//        rule.setCheckboxSize(1);
//        rule.setJudgeSize(1);
//        rule.setFillInSize(1);
//        ExamPaper paper = paperService.build(rule);

        examInfoMapper.addExamInfo(examInfo);

        examInfo.getExamTheory().setExamId(examInfo.getId());
        examInfo.getExamTheory().setPaperId(examInfo.getExamTheory().getPaperId());
        examInfo.getExamTheory().setDefault();
        examTheoryMapper.addExamTheory(examInfo.getExamTheory());
    }

    @Override
    @Transactional
    public void updateExam(ExamInfo examInfo) {
        if (examInfo.getId() == null) {
            throw new IllegalArgumentException("id is null");
        }
        examInfo.verifyComplete();

        ExamInfo oldInfo = getExamInfo(examInfo.getId());
        if (oldInfo == null) {
            return;
        }
        if (oldInfo.getStatus() == ExamStatusEnum.UN_ENABLED.getStatus()
                && examInfo.getStatus() != ExamStatusEnum.UN_ENABLED.getStatus()) {
            checkExamInProgressOnly();
        }

        ExamTheory theory = examInfo.getExamTheory();
        if (theory.getId() == null) {
            throw new IllegalArgumentException("subject id is null");
        }
        examTheoryMapper.updateExamTheory(theory);

        examInfoMapper.updateExamInfo(examInfo);

        onExamStatusChange(examInfo.getId() ,oldInfo.getStatus() ,examInfo.getStatus());
    }

    private void onExamStatusChange(int examId ,int oldStatus ,int newStatus){
        if (oldStatus == ExamStatusEnum.IN_PROGRESS.getStatus()
                && (newStatus != ExamStatusEnum.UN_ENABLED.getStatus() || newStatus != ExamStatusEnum.ENDED.getStatus())
        ) {
            scoreService.onExamEnd(examId);
        }
    }

    /**
     * 检查是否有进行中的考核
     */
    private void checkExamInProgressOnly() {
        ExamInfo last = getLastExam();
        if (last != null) {
            if (last.getStatus() != ExamStatusEnum.ENDED.getStatus()) {
                throw new IllegalArgumentException("already unfinished exam[" + last.getId() + ": " + last.getExamName() + "]");
            }
        }
    }
}
